package com.stars.services.impl.mygenerate;/**
 * Created by luodajie on 2019/1/6.
 */

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.stars.common.MyStrRegex;
import com.stars.common.ObjectCopyUtils;
import com.stars.common.WheterYN;
import com.stars.common.base.*;
import com.stars.common.valid.MyException;
import com.stars.dao.mapper.mygenerate.CgFormFieldMapper;
import com.stars.dao.mapper.mygenerate.CgFormHeadMapper;
import com.stars.entity.ListPage;
import com.stars.entity.mygenerate.CgFormField;
import com.stars.entity.mygenerate.CgFormHead;
import com.stars.entity.mygenerate.MysqlAutoGenerateTable;
import com.stars.entity.mygenerate.command.CgFormHeadCommand;
import com.stars.services.impl.BaseAccessServiceImpl;
import com.stars.services.mygenerate.CgFormHeadServices;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author :dj
 * @version : 1.0.0
 * @description
 * @Date 2019-01-06 11:25
 * @note
 */
@Slf4j
@Service
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
public class CgFormHeadServicesImpl extends BaseAccessServiceImpl<CgFormHeadMapper, CgFormHead> implements
        CgFormHeadServices {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private CgFormHeadMapper cgFormHeadMapper;
    @Autowired
    private CgFormFieldMapper cgFormFieldMapper;

    @Override
    public PageInfo<CgFormHead> pageQuery(Integer pageNum, Integer pageSize, CgFormHeadCommand cgFormHead) throws Exception {
        ListPage<CgFormHeadCommand> listPage = new ListPage<>(pageNum, pageSize, cgFormHead);
        PageHelper.startPage(pageNum, pageSize);
        List<CgFormHead> blogList = cgFormHeadMapper.findByPage(listPage);
        PageInfo<CgFormHead> pageInfo = new PageInfo<>(blogList);
        return pageInfo;
    }

    @Override
    public ResultMsg add(CgFormHead cgFormHead) throws Exception {
        //1，校验表头
        checkHeadForm(cgFormHead,false);
        //2，校验字段
        checkField(cgFormHead.getDataJson());

        if (StringUtils.isBlank(cgFormHead.getId())) {
            cgFormHead.setId(BaseUUID.getUUID());
        }
        cgFormHeadMapper.insert(cgFormHead);
        addField(cgFormHead);
        return ResultMsg.success();
    }

    @Override
    public ResultMsg update(CgFormHead cgFormHead) throws Exception {
        //1，校验表头
        checkHeadForm(cgFormHead,true);

        //2，校验字段
        checkField(cgFormHead.getDataJson());
        CgFormHead cgFormHead1 = this.selectById(cgFormHead.getId());
        ObjectCopyUtils.copyPropertiesIf(cgFormHead, cgFormHead1);
        cgFormHead1.setUpdateDate(new Date());
        if (null == cgFormHead1.getVersion()) {
            cgFormHead1.setVersion(0);
        }
        cgFormHead1.setVersion(cgFormHead1.getVersion() + 1);
        cgFormHeadMapper.updateByPrimaryKey(cgFormHead1);
        //删除原来的字段
        List<CgFormField> cgFormFieldList = cgFormFieldMapper.findTableId(cgFormHead.getId());
        for (CgFormField c : cgFormFieldList) {
            cgFormFieldMapper.deleteByPrimaryKey(c.getId());
        }
        addField(cgFormHead);
        return ResultMsg.success();
    }

    private void addField(CgFormHead cgFormHead){
        List<CgFormField> cgFormFieldList = jsonToList(cgFormHead.getDataJson());
        int i = 0;
        for (CgFormField cgFormField : cgFormFieldList) {
            cgFormField.setTableId(cgFormHead.getId());
            cgFormField.setId(BaseUUID.getUUID());
            cgFormField.setFiledOrder(i);
            cgFormFieldMapper.insert(cgFormField);
            i++;
        }
    }

    @Override
    public ResultMsg delById(String ids) throws Exception {
        if (StringUtils.isNotBlank(ids)) {
            for (String id : ids.split(BaseConstant.SPOT)) {
                CgFormHead cgFormHead = cgFormHeadMapper.selectByPrimaryKey(id);
                cgFormHeadMapper.delete(cgFormHead);
                //先删除原来表
                String dropSql = "DROP TABLE IF EXISTS  `" + cgFormHead.getTableName() + "` ;";
                jdbcTemplate.execute(dropSql);
                List<CgFormField> fieldList = cgFormFieldMapper.findTableId(id);
                for (CgFormField cgFormField : fieldList) {
                    cgFormFieldMapper.delete(cgFormField);
                }
            }
            return ResultMsg.success();
        }
        return ResultMsg.failure("删除失败!");
    }

    @Override
    public CgFormHead findById(String id) {
        if(StringUtils.isBlank(id)){
            return null;
        }
        return cgFormHeadMapper.selectByPrimaryKey(id);
    }

    @Override
    public ResultMsg createDBTable(String id) throws Exception {
        if (StringUtils.isBlank(id)) {
            return ResultMsg.failure("没有选择成表的数据！");
        }
        CgFormHead cgFormHead = cgFormHeadMapper.selectByPrimaryKey(id);
        if (cgFormHead == null) {
            return ResultMsg.failure("数据没有表的数据！");
        }
        //找到表字段
        List<CgFormField> cgFormFieldList = cgFormFieldMapper.findTableId(cgFormHead.getId());
        if (cgFormFieldList.isEmpty()) {
            return ResultMsg.failure("没有找到表字段的数据！");
        }
        //先删除原来表
        String dropSql = "DROP TABLE IF EXISTS  `" + cgFormHead.getTableName() + "` ;";
        jdbcTemplate.execute(dropSql);
        log.info("==========================先删除原来表================================");
        String jdbcSql = MysqlAutoGenerateTable.createMysqlDbTable(cgFormHead.getTableName(), cgFormFieldList);
        log.info("==========================创建数据库语句================================");
        System.out.println(jdbcSql);
        log.info("---------------------------------------------------------");
        jdbcTemplate.execute(jdbcSql);
        log.info("---------------------------生成数据库表成功---------------");
        log.info("---------------------------如果是树形，生成函数---------------");
        //添加执行基础字段，版本号
        if (StringUtils.isNotBlank(cgFormHead.getIsCreateAppOrg())) {
            String baseField = MysqlAutoGenerateTable.addBaseField(cgFormHead.getTableName(), cgFormHead.getIsCreateAppOrg());
            log.info("---------------------------添加其他字段---------------");
            log.info(baseField);
            jdbcTemplate.execute(baseField);
        }
        if (WheterYN.YES.getValue().equals(cgFormHead.getIsTree())) {
            //如果存在，先删除
            log.info("---------------------------父函数---------------");
            String dropTreeParentFunction = "DROP FUNCTION IF EXISTS  `" + cgFormHead.getTableName() + "_get_parent` ;";
            jdbcTemplate.execute(dropTreeParentFunction);
            String parentFunction = MysqlAutoGenerateTable.createTreeParentFunction(cgFormHead.getTableName());
            jdbcTemplate.execute(parentFunction);
            log.info(parentFunction);
            log.info("---------------------------父函数，生成功---------------");
            log.info("---------------------------子函数---------------");
            String dropTreeChildFunction = "DROP FUNCTION IF EXISTS  `" + cgFormHead.getTableName() + "_get_child` ;";
            jdbcTemplate.execute(dropTreeChildFunction);
            String treeChildFunction = MysqlAutoGenerateTable.createTreeChildFunction(cgFormHead.getTableName());
            jdbcTemplate.execute(treeChildFunction);
            log.info("---------------------------子函数，生成功---------------");

        }
        cgFormHead.setIsDbSynchronization(WheterYN.YES.getValue());
        cgFormHeadMapper.updateByPrimaryKey(cgFormHead);
        return ResultMsg.success("生成数据库表成功");
    }

    /**
     * json 转字段实体集合
     * @param dataJson
     * @return
     */
    private List<CgFormField> jsonToList(String dataJson) {
        Gson gson = new Gson();
        if (StringUtils.isBlank(dataJson)) {
            return new ArrayList<>();
        }
        List<CgFormField> cgFormFieldList = gson.fromJson(dataJson, new TypeToken<List<CgFormField>>() {
        }.getType());
        return cgFormFieldList;
    }
    /**
     * 校验表单
     *
     * @param cgFormHead
     * @return
     */
    private void checkHeadForm(CgFormHead cgFormHead,boolean isAddOrUpdate) throws Exception {
        CgFormHeadCommand command = new CgFormHeadCommand();
        command.setTableNameSel(cgFormHead.getTableName());
        if(isAddOrUpdate){
            command.setId(cgFormHead.getId());
        }
        List<CgFormHead> cgFormHeadList = cgFormHeadMapper.findByTableNameOrId(command);
        if (cgFormHeadList.size() > 0) {
            throw new MyException("表名已经存在！");
        }
        if (!MyStrRegex.strValidRegex(cgFormHead.getTableName(), MyStrRegex.TABLE_NAME_REGEX)) {
            throw new MyException("表名规则：小写下划线，长度5-20,字符，不能以下划线开头结尾");
        }
        //模块包名小写，不能为空
        if (!MyStrRegex.strValidRegex(cgFormHead.getModuleName(), MyStrRegex.MODULE_NAME)) {
            throw new MyException("模块包名小写，不能为空");
        }
    }

    /**
     * 校验字段
     * @param dataJson
     * @return
     */
    private void checkField(String dataJson) {
        ResultMsg fieldResult = null;
        Map<String, String> validName = new HashMap<>();
        List<CgFormField> cgFormFieldList = jsonToList(dataJson);
        for (CgFormField cgFormField : cgFormFieldList) {
            //校验字段
            validName.put(cgFormField.getName(), cgFormField.getName());
            if("id".equals(cgFormField.getName())){
                continue;
            }
            if (!MyStrRegex.strValidRegex(cgFormField.getName(), MyStrRegex.FIELD_NAME_REGEX)) {
                throw new MyException(cgFormField.getName() + ":表字段：小写下划线数字，长度3-30,字符，不能以数字开头，不能以下划线开头结尾，");
            }
        }

        if (validName.size() != cgFormFieldList.size()) {
            throw new MyException("请检查表字段,有重复");
        }
    }
}
